package com.wanfajie.smsdistribute.common.activity

import android.content.pm.PackageManager
import android.os.Build
import android.support.annotation.CallSuper
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import android.support.v7.view.ActionMode
import android.text.Html
import android.util.Log
import com.wanfajie.smsdistribute.MyApplication
import com.wanfajie.smsdistribute.R
import com.wanfajie.smsdistribute.common.fragment.BaseFragment
import com.wanfajie.smsdistribute.util.getDeniedPermissions
import com.wanfajie.smsdistribute.util.getPermissionLocateName
import com.wanfajie.smsdistribute.util.jumpPermissionSetting

abstract class BaseActivity : AppCompatActivity() {

    companion object {
        private const val PERMISSION_REQUEST_CODE = 2233
    }

    protected open val requiredPermissions : Array<String>?
        get() = null

    private val TAG = "BaseActivity_${javaClass.simpleName}"

    private var isDialogShowing = false

    private fun noCoverageShow(builderCreateFn: () -> AlertDialog.Builder) {
        if (isDialogShowing) return

        val builder = builderCreateFn.invoke()

        builder.setCancelable(false)
                .setNegativeButton(R.string.quit) { _, _ -> finish() }
                .setOnDismissListener { isDialogShowing = false }
                .create()
                .show()

        isDialogShowing = true
    }

    private fun showPermissionDialog(permissions : Array<String>) = noCoverageShow {
        val permitStr = permissions.joinToString("、") { getPermissionLocateName(it) }

        AlertDialog.Builder(this)
                .setTitle(R.string.perm_request_dialog_title)
                .setMessage(getString(R.string.perm_request_dialog_content, permitStr))
                .setPositiveButton(R.string.ok) { dialog, _ ->
                    requestPermissions(permissions)
                    dialog.dismiss()
                }
    }

    private fun showJumpSettingsDialog(permissions: List<String>) = noCoverageShow {
        val permitStr = permissions.joinToString("<br>", postfix = "<br>") {
            getPermissionLocateName(it)
        }
        val content = getString(R.string.jump_permission_settings_dialog_content, permitStr)

        AlertDialog.Builder(this)
                .setTitle(R.string.perm_jump_dialog_title)
                .setMessage(Html.fromHtml(content))
                .setPositiveButton(R.string.ok) { dialog, _ ->
                    jumpPermissionSetting(this)
                    dialog.dismiss()
                }
    }

    private fun requestPermissions(denied : Array<String>) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(denied, PERMISSION_REQUEST_CODE)
        } else {
            Log.e(TAG, "API版本(${Build.VERSION.SDK_INT})过低, 无法请求获取权限")
        }
    }

    private fun getCheckedDntAsk(permission: List<String>): List<String> {
        return permission.filter {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                !shouldShowRequestPermissionRationale(it)
            } else false
        }
    }

    private fun checkDeniedPermissions(denied : List<String>) {
        if (denied.isNotEmpty()) {
            Log.d(TAG, "缺少权限: $denied")

            val dntAskList = getCheckedDntAsk(denied)
            if (dntAskList.isEmpty() || MyApplication.isFirstStart) {
                showPermissionDialog(denied.toTypedArray())
            } else {
                // 存在false的情况为用户选择了不再询问
                showJumpSettingsDialog(dntAskList)
            }
        } else {
            Log.d(TAG, "权限满足")
            onAllPermissionsGranted()
        }
    }

    override fun onStart() {
        super.onStart()

        requiredPermissions?.let {
            if (it.isNotEmpty()) {
                val denied = getDeniedPermissions(this, *it)
                checkDeniedPermissions(denied)
            }
        }
    }

    open fun onAllPermissionsGranted() = Unit

    final override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode != PERMISSION_REQUEST_CODE) return

        val denied = permissions.filterIndexed { i, _ ->
            grantResults[i] == PackageManager.PERMISSION_DENIED
        }.toList()

        checkDeniedPermissions(denied)
    }

    var supportActionMode: ActionMode? = null
        private set(v) { field = v }

    @CallSuper
    override fun onSupportActionModeStarted(mode: ActionMode) {
        super.onSupportActionModeStarted(mode)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = resources.getColor(R.color.colorAccentBlack)
        }
        supportActionMode = mode
    }

    @CallSuper
    override fun onSupportActionModeFinished(mode: ActionMode) {
        super.onSupportActionModeFinished(mode)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = resources.getColor(R.color.colorPrimaryDark)
        }
        supportActionMode = null
    }

    var actionMode: android.view.ActionMode? = null
        private set(v) { field = v }

    @CallSuper
    override fun onActionModeStarted(mode: android.view.ActionMode?) {
        super.onActionModeStarted(mode)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = resources.getColor(R.color.colorAccentBlack)
        }
        actionMode = mode
    }

    @CallSuper
    override fun onActionModeFinished(mode: android.view.ActionMode?) {
        super.onActionModeFinished(mode)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            window.statusBarColor = resources.getColor(R.color.colorPrimaryDark)
        }
        actionMode = null
    }

    fun finishActionMode() {
        actionMode?.finish()
        supportActionMode?.finish()
    }

    override fun onBackPressed() {
        var consumed = false
        supportFragmentManager.fragments.forEachIndexed { i, it ->
            if (it !is BaseFragment) return@forEachIndexed

            if (it.userVisibleHint) {
                consumed = it.onBackPressed()
                Log.d(TAG, "触发BaseFragment.onBackPressed(): " +
                        "[consumed=$consumed, index=$i, tag=${it.tag}]")
                return@forEachIndexed
            }
        }

        if (!consumed) super.onBackPressed()
    }
}